package com.ganhuoshitang.限流算法;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 2、漏桶算法
 *
 * 优缺点
 *  有效的挡住了外部的请求，保护了内部的服务不会过载
 *  内部服务匀速执行，无法应对流量洪峰，无法做到弹性处理突发任务
 *  任务超时溢出时被丢弃。现实中可能需要缓存队列辅助保持一段时间
 */
public class Barrel {
    public static void main(String[] args) {
        //桶，用阻塞队列实现，容量为3
        final LinkedBlockingQueue<Integer> que = new LinkedBlockingQueue(3);
        //定时器，相当于服务的窗口，2s处理一个
        ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public  void run() {
                int v = que.poll();
                System.out.println(getNowTime() + " 处理：" + v);
            }
        }, 3000, 2000, TimeUnit.MILLISECONDS);
        //无数个请求，i 可以理解为请求的编号
        int i = 0;
        while (true) {
            i++;
            try {
                //如果是put，会一直等待桶中有空闲位置，不会丢弃
                // que.put(i);
                // 等待1s如果进不了桶，就溢出丢弃
                boolean offer = que.offer(i, 1000, TimeUnit.MILLISECONDS);
                System.out.println(getNowTime() + " put:" + i + " >> " + (offer ? "成功" : "失败") + "; 当前队列容量："+ que.size());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    public static String getNowTime(){
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        //        System.out.println("当前时间：" + sdf.format(d));
        return sdf.format(d);
    }
}
